#include "userdata.h"
#include "MongoDBDefine.h"
#include "mongoagent.h"
#include "log/log.h"
#include <QDateTime>
#include <iostream>

#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/builder/stream/array.hpp>
#include <bsoncxx/builder/stream/helpers.hpp>
#include <bsoncxx/types.hpp>

using bsoncxx::builder::stream::document;
using bsoncxx::builder::stream::array;

namespace HIM {

Q_GLOBAL_STATIC(UserData, userData)

UserData* UserData::instance()
{
    return userData();
}

UserData::UserData()
{   
    if(MONGOAGENT.getConnectStatus())
    {
        document doc{};
        doc <<UserKeyLists[0]<<"001";
        auto fin = MONGOAGENT.getClient()[DEFAULT_DB][USER_COLLECTION].find(doc.view());
        if(fin.begin()==fin.end())
        {
            QDateTime current_date_time =QDateTime::currentDateTime();
            std::string creationTime = current_date_time.toString("yyyy.MM.dd hh:mm:ss").toStdString();

            doc <<UserKeyLists[ACCOUNT]<< "Admin"<<UserKeyLists[ROLE]<< "admin"
               <<UserKeyLists[User_Creation_Time]<<creationTime<<UserKeyLists[Last_Login_Time]<< "-"
              <<UserKeyLists[PASSWORD]<< "8888";
            MONGOAGENT.insert(DEFAULT_DB,USER_COLLECTION,doc.view());
        }
    }
}

std::string UserData::getValue(UserKey filtel_key, std::string filtel_Value , std::string get_Key)
{   
    if(MONGOAGENT.getConnectStatus())
    {
        document doc{};
        doc <<UserKeyLists[filtel_key]<<filtel_Value;
        auto cursor = MONGOAGENT.getClient()[DEFAULT_DB][USER_COLLECTION].find(doc.view());
        if(cursor.begin()!=cursor.end())
        {
            auto doc = *cursor.begin();
            bsoncxx::document::element element = doc[get_Key];
            if(element)
                return  element.get_utf8().value.to_string();
            else
            {
                HIM_ERROR("[DBerror3] load password error.");
                return "";
            }
        }
        else
        {
            HIM_ERROR("[DBerror2] load password error.");
            return "";
        }
    }
    else
        return "";
}

bool UserData::findAccount(std::string accountValue)
{    
    if(MONGOAGENT.getConnectStatus())
    {
        document doc{};
        doc <<UserKeyLists[1]<<accountValue;
        auto cursor = MONGOAGENT.getClient()[DEFAULT_DB][USER_COLLECTION].find(doc.view());
        if(cursor.begin()!=cursor.end())
            return true;
        else
            return false;
    }
    else
        return false;
}

int UserData::getUserCount()
{
    return MONGOAGENT.count(DEFAULT_DB, USER_COLLECTION, document{});
}

void UserData::addUser(std::map<std::string,std::string> userNew)
{
    document doc{};

    for (auto it : userNew)
        doc<<it.first<<it.second;

    MONGOAGENT.insert(DEFAULT_DB,USER_COLLECTION,doc.view());
}

void UserData::deleteUser(std::string deId)
{
    document doc{};
    doc <<UserKeyLists[0]<< deId;
    MONGOAGENT.remove(DEFAULT_DB, USER_COLLECTION, doc);
}

void UserData::updateUser(std::string upId , std::map<std::string,std::string> userUpdata )
{
    document filter{};
    document updoc{};

    for (auto it : userUpdata)
        updoc<<it.first<<it.second;

    filter << UserKeyLists[0] << upId;
    MONGOAGENT.update(DEFAULT_DB, USER_COLLECTION, filter, updoc.view());
}

void UserData::updateSingleValue(UserKey filtel_key, std::string filtel_Value , UserKey up_key, std::string up_value)
{
    if(MONGOAGENT.getConnectStatus())
    {
        document doc{};
        doc <<UserKeyLists[filtel_key]<<filtel_Value;
        auto cursor = MONGOAGENT.getClient()[DEFAULT_DB][USER_COLLECTION].find(doc.view());
        if(cursor.begin()!=cursor.end())
        {
            std::map<std::string,std::string> userD;
            auto doc = *cursor.begin();
            for(int i = 0 ; i < 6 ; ++i)
            {
                bsoncxx::document::element element = doc[UserKeyLists[i]];
                if(element)
                {
                    if(i!=up_key)
                        userD[UserKeyLists[i]]=element.get_utf8().value.to_string();
                    else
                        userD[UserKeyLists[i]]=up_value;
                }
                else
                    HIM_ERROR("[DBerror1] data load error.");
            }

            document updoc{};
            for (auto it : userD)
                updoc<<it.first<<it.second;

            MONGOAGENT.update(DEFAULT_DB, USER_COLLECTION, doc, updoc.view());
        }
        else
        {
            HIM_ERROR("[DBerror] data query error.");
        }
    }
}

void UserData::loadUser(std::vector<std::vector<std::string>>& userData)
{  
    if(MONGOAGENT.getConnectStatus())
    {
        auto cursor = MONGOAGENT.getClient()[DEFAULT_DB][USER_COLLECTION].find({});
        for (auto doc : cursor)
        {
            std::vector<std::string> user;
            for(int i = 0 ; i < 5 ; ++i)
            {
                bsoncxx::document::element element = doc[UserKeyLists[i]];
                if(element)
                    user.push_back(element.get_utf8().value.to_string());
                else
                    HIM_ERROR("[DBerror1] User load error.");
            }
            userData.push_back(user);
        }
    }
}
}
